<?php

declare(strict_types=1);

namespace App\CustHub\Mapper;

use App\CustHub\Constants\RoomJoinSceneConstants;
use App\CustHub\Model\ChRoomMember;
use Carbon\Carbon;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\Collection;
use Hyperf\DbConnection\Db;
use Mine\Abstracts\AbstractMapper;
use Mine\MineModel;

class ChRoomMemberMapper extends AbstractMapper
{
    public function assignModel()
    {
        $this->model = ChRoomMember::class;
    }

    public function getRoomMemberPageList(array $data): array
    {
        $pageSize = $data['page_size'] ?? MineModel::PAGE_SIZE;

        $query = $this->model::query()
            ->select(['id','user_id','nickname','name','avatar','is_out','join_time','out_time','inviter_id','is_friend','member_type','join_scene','corp_id','corp_name','corp_full_name','is_black','is_white'])
            ->with(['inviter'=>function ($query) use ($data){
                $query->select(['id','user_id','nickname','avatar']);
            }]);
        $data = $this->handleSearch($query,$data)->groupBy('user_id')->paginate((int)$pageSize);
        $data->getCollection()->transform(function ($item){
            $item->join_time_text = datetime($item->join_time,'Y-m-d');
            $item->join_scene_text = RoomJoinSceneConstants::getMessage($item->join_scene);
            $item->corp = [
                'corp_name' => $item->corp_name,
                'corp_full_name' => $item->corp_full_name
            ];
            unset($item->join_time,$item->join_scene);
            return $item;
        });
        return $this->setPaginate($data);
    }

    /**
     * 获取群内机器人列表
     * @param array $paras
     * @return \Hyperf\Collection\Collection
     */
    public function getRoomRobotList(mixed $roomWxid): \Hyperf\Collection\Collection
    {
        $list = Db::table('ch_room_member as crm')
            ->select(['cr.id','cr.nickname','cr.avatar','cr.corp_id','cr.corp_name','cr.login_status','crm.is_owner'])
            ->join('ch_robot as cr','cr.user_id','=','crm.user_id')
            ->where('crm.room_wxid',$roomWxid)
            ->get();
        return $list;
    }

    /**
     * 获取指定企业群成员列表
     * @param string $roomWxid
     * @param string $userId
     * @param int $corpId
     * @return array
     */
    public function fetchCorpRoomMembers(string $roomWxid,string $userId,int $corpId,string $keyword,int $pageSize): array
    {
        $p = $this->model::query()
            ->select(['id','nickname','avatar','corp_id','corp_name','corp_full_name','member_type'])
            ->with(['corp'=>function ($query) {
                $query->select(['id','corp_name']);
            }])
            ->when(!empty($keyword),function ($query) use ($keyword){
                $query->where('nickname','like','%'.$keyword.'%');
            })
            ->where('room_wxid',$roomWxid)
            ->where('user_id','<>',$userId)
//            ->where('corp_id',$corpId)
            ->paginate($pageSize);

        $p->getCollection()->transform(function ($item){
            $item->corp = [
                'corp_name' => $item->corp_name,
                'corp_full_name' => $item->corp_full_name
            ];
            return $item;
        });

        return  $this->setPaginate($p);
    }

    /**
     * 退出群聊
     * @param mixed $roomWxid
     * @param mixed $userId
     * @return bool|int
     */
    public function outRoom(mixed $roomWxid,mixed $userId): bool|int
    {
        return $this->model::query()
            ->where('room_wxid',$roomWxid)
            ->where(function ($query) use ($userId){
                if(is_array($userId)){
                    $query->whereIn('user_id',$userId);
                }else{
                    $query->where('user_id',$userId);
                }
            })
            ->update([
                'is_out'=>1,
                'out_time' => Carbon::now()->toDateTimeString()
            ]);
    }

    /**
     * 标记群成员为已退出
     * @param string $roomWxid
     * @return void
     */
    public function markMembersAsDeleted(string $roomWxid): void
    {
        ChRoomMember::query()->where('room_wxid',$roomWxid)->update([
            'is_out' =>1,
            'out_time' =>Carbon::now()->toDateTimeString(),
        ]);
    }

    /**
     * 获取群成员信息
     * @param mixed $roomWxid
     * @param mixed $userId
     * @return ChRoomMember|\Hyperf\Database\Model\Model|string|Builder|null
     */
    public function findByRoomWxidAndUserId(mixed $roomWxid, mixed $userId): ChRoomMember|\Hyperf\Database\Model\Model|string|Builder|null
    {
        return $this->model::query()
            ->where('room_wxid',$roomWxid)
            ->where('user_id',$userId)
            ->first();
    }


    /**
     * 更新最后发言时间
     * @param mixed $roomWxid
     * @param mixed $userId
     */
    public function upLastSendTimeByRoomWxidAndUserId(mixed $roomWxid, mixed $userId)
    {
        return $this->model::query()
            ->where('room_wxid',$roomWxid)
            ->where('user_id',$userId)
            ->update(['send_last_time'=>time()]);
    }

    /**
     * 检查群成员是否存在
     * @param string $roomWxid
     * @param string $userId
     * @return bool
     */
    public function checkRoomMemberExist(string $roomWxid,string $userId,?int $isOut = null)
    {
        return $this->model::query()
            ->where('room_wxid',$roomWxid)
            ->where('user_id',$userId)
            ->when(!is_null($isOut),function ($query) use ($isOut){
                $query->where('is_out',$isOut);
            })
            ->exists();
    }

    /**
     * 判断群成员是否是群主或管理员
     * @param string $roomWxid
     * @param string $userId
     * @return bool
     */
    public function isRoomOwnerOrAdmin(string $roomWxid,string $userId): bool
    {
        return $this->model::query()
            ->where('room_wxid',$roomWxid)
            ->where('user_id',$userId)
            ->where(function ($query) {
                $query->where('is_owner',1)->orWhere('is_admin',1);
            })->exists();
    }

    /**
     * 获取用户加入的群列表
     * @param string $userId
     * @return array
     */
    public function getRoomWxidsByUserId(string $userId): array
    {
        return $this->model::query()
            ->where('user_id',$userId)
            ->pluck('room_wxid')
            ->unique()
            ->toArray();
    }

    public function handleSearch(Builder $query, array $params): Builder
    {
        if(!empty($params['nickname'])){
            $query->where('nickname','like','%'.$params['nickname'].'%');
        }

        if(isset($params['member_type']) && filled($params['member_type'])){
            $query->where('member_type',$params['member_type']);
        }

//        if(!empty($params['corp_id'])){
//            $query->where('corp_id',$params['corp_id']);
//        }

        if(isset($params['is_friend']) && filled($params['is_friend'])){
            $query->where('is_friend',$params['is_friend']);
        }

        if(!empty($params['room_wxid'])){
            if(is_array($params['room_wxid'])){
                $query->whereIn('room_wxid',$params['room_wxid']);
            }else{
                $query->where('room_wxid',$params['room_wxid']);
            }
        }

        if(!empty($params['inviter_id'])){
            $query->where('inviter_id',$params['inviter_id']);
        }

        if(!empty($params['keyword'])){
            if(is_numeric($params['keyword'])){
                $query->where('user_id',$params['keyword']);
            }else{
                $query->where('nickname','like','%'.$params['keyword'].'%');
            }
        }

        if(isset($params['is_out']) && filled($params['is_out'])){
            $query->where('is_out',$params['is_out']);
        }

        if(!empty($params['join_start_time']) && !empty($params['join_end_time'])){
            $query->whereBetween('join_time',[strtotime($params['join_start_time']),strtotime($params['join_end_time'])]);
        }

        if(isset($params['join_scene']) && filled($params['join_scene'])){
            $query->where('join_scene',$params['join_scene']);
        }

        return $query;
    }

}